package edu.hawaii.halealohacli.jcev.command;

import java.text.DecimalFormat;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.WattDepotClient;
import org.wattdepot.resource.sensordata.jaxb.SensorData;
import org.wattdepot.resource.source.jaxb.Source;

/**
 * This class gets the current power of a wattDepot client.
 * @author Eldon Visitacion
 */
public class CurrentPower implements Command {
  /** name of source. */
  private String name;
  /** current power used in kW. */
  private double power;
  /** stores the current timestamp. */
  private XMLGregorianCalendar timestamp;
  /** for testing. checks if there is a error w/ arguments. */
  private boolean testArg;
  
  /**
   * Constructs a CurrentPower object.
   */
  public CurrentPower() { 
    // Fields should be initialized using setAll.
  }
  
  /**
   * Create an object which gets the Current Power usage.
   * 
   * @param client The WattDepotClient which is being used to collect the data.
   * @param source The WattDepot Source name
   * @return A CurrentPower Object
   * @throws Exception A generic Exception, or the NotAuthorizedException,
   * ResourceNotFoundException, BadXmlException, or MiscClientException thrown by the
   * WattDepotClient.
   */
  public CurrentPower setAll(WattDepotClient client, String source) throws Exception {
    SensorData data;
    this.name = source;
    data = client.getLatestSensorData(source);
    
    // ensures the power is set to a nicer formatted double value. (setPower)
    DecimalFormat format = new DecimalFormat( "###0.00" );
    double powerValue = data.getPropertyAsDouble(SensorData.POWER_CONSUMED) / 1000;
    double returnValue = new Double(format.format(powerValue)).doubleValue();
    this.power =  returnValue;
    
    // (set Time)
    this.timestamp = data.getTimestamp();
    return this;
  }
  
  /**
   * Verifies the arguments, executes the command, and prints the results to the screen.
   * 
   * @param args Space delimited string of arguments (i.e. "arg1 arg2 arg3").
   * @param client The WattDepot client that will be performing the queries.
   * @throws Exception If an exception was thrown by the command (i.e. bad arguments) or any of its
   * function calls.
   */
  @Override
  public void execute(String args, WattDepotClient client) throws Exception {
    if (args.length() > 0) {
      String[] splitArgs = args.split("[ ]");
      // Checks for exactly 2 arguments
      if (splitArgs.length > 1) {
        this.testArg = false;
        throw new Exception("Error: More than 1 argument.\n"
            + "Correct syntax: current-power [tower | lounge]");
      }
      // Test passes, execute this block.
      else {
        List<Source> sources = client.getSources();
        boolean match = false;
        // Checks if the 2nd argument matches a source name. Throw exception if no matches.
        for (Source source : sources) {
          if (splitArgs[0].equals(source.getName())) {
            match = true;
          }
        }
        if (!match) {
          this.testArg = false;
          throw new Exception("Error: Source \"" + splitArgs[0] + "\" does not exist.");
        }
        this.testArg = true;
        setAll(client, splitArgs[0]);
        System.out.println(this.toString());
        
      }
    }
    else {
      this.testArg = false;
      throw new Exception("Bad input: No arguments given.");
    }
  }
  
  /**
   * gets the name of the source.
   * @return name of source
   */
  public String getName() {
    return this.name;
  }
  
  /**
   * Returns power value.
   * @return latest read power
   */
  public double getPowerReading() {
    return this.power;
  }
  
  /**
   * Returns the timestamp.
   * @return Current timestamp
   */
  public XMLGregorianCalendar getTimeStamp() {
    return this.timestamp;
  }
  
  /**
   * Tells JUnit if there was an error with arguments.
   * @return argument passed (true) or failed (false)
   */
  public boolean testArgs() {
    return testArg;
  }
  
  /**
   * Returns readable output to the user.
   * @return output that can be read by user.
   */
  @Override
  public String toString() {
    return this.name + "'s power as of " + this.timestamp.getYear() + "-" 
          + this.timestamp.getMonth() + "-" + this.timestamp.getDay() + " "
          + this.timestamp.getHour() + ":" + this.timestamp.getMinute() + ":"
          + this.timestamp.getSecond() + " was " + this.power + "kW";
  }
  
  /**
   * Returns the string to be printed by the help command. Format:
   * "command-name [args1] [args2] .... \nDescription"
   * 
   * @return The string to be printed by the help command.
   */
  @Override
  public String getHelpString() {
    return "current-power [tower | lounge]\n"
        + "Returns the current power in kW for the associated tower or lounge.";
  }
}
